package com.sdhs.analyze.service.monitor;

import com.alibaba.fastjson.JSON;
import com.sdhs.analyze.bean.DicNodeType;
import com.sdhs.analyze.bean.InfoNodeStatus;
import com.sdhs.analyze.bean.datatransfer.InfoGantryUploadStatus;
import com.sdhs.analyze.bean.gantrymonitor.DataTransferMonitorInfo;
import com.sdhs.analyze.bean.monitorinfo.DataTransInfo;
import com.sdhs.analyze.bean.monitorinfo.GantryMonitorInfo;
import com.sdhs.analyze.bean.org.OrgInfo;
import com.sdhs.analyze.common.BizConstants;
import com.sdhs.analyze.dao.datatransfer.DataTransferMapper;
import com.sdhs.analyze.utils.DateUtils;
import com.sdhs.analyze.utils.RedisUtil;
import com.sdhs.analyze.utils.StatusCheckUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class DataTransferService {

    @Autowired
    private NodeStatusService nodeStatusService;

    @Autowired
    private DataTransferMapper dataTransferMapper;

    @Autowired
    private RedisUtil redisUtil;

    private String split = "|";

    /**
     * 检测门架至运行监测系统、门架至省中心、门架至部中心的数据传输状态
     */
    public void tradeTransferMonitor(
            OrgInfo orgInfo,
            Map<String, InfoNodeStatus> nodeStatusMap,
            Map<String, DicNodeType> nodeTypeMap,
            InfoNodeStatus parentNodeStatus,
            GantryMonitorInfo gantryMonitorInfo) {

        /* 获取最新检测信息 */
        DataTransferMonitorInfo dataTransferMonitorInfo = getDataTransferMonitorInfoByOrgId(orgInfo.getOrgId());
        /* 无状态，不检测 */
        if (dataTransferMonitorInfo == null) {
            return;
        }

        /* 新状态 */
        List<InfoNodeStatus> newNodeStatus = new ArrayList<>();

        Date now = new Date();

        String orgName = orgInfo.getOrgName();

        String remark = "";

        /* 交易传输状态 */
        InfoNodeStatus tradeTransNodeStatus =
                nodeStatusService.makeNodeStatus(
                        nodeTypeMap.get(BizConstants.NODE_TYPE_TRADEDATATRANSFER), orgInfo.getOrgId(), "",
                        orgInfo.getOrgId(),
                        BizConstants.NODE_STATUS_UNKNOWN, orgInfo.getOrgId(), "", new Date(0));

        /* 至运行监测交易传输状态 */
        if (dataTransferMonitorInfo.getMonitorTradeTransferTime() != null) {
            long transferTimeDiff = now.getTime() - dataTransferMonitorInfo.getMonitorTradeTransferTime().getTime();
            int transTimeDiffMinute = (int) (transferTimeDiff / 60000.0);
            InfoNodeStatus brokenNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    transTimeDiffMinute,
                    now,
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_BROKEN_MONITOR),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_BROKEN_MONITOR).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    tradeTransNodeStatus);
            newNodeStatus.add(brokenNodeStatus);

            long bizTimeDiff = dataTransferMonitorInfo.getMonitorTradeTransferTime().getTime()
                    - dataTransferMonitorInfo.getMonitorTradeBizTime().getTime();
            int bizTimeDiffMinute = (int) (bizTimeDiff / 60000.0);
            InfoNodeStatus delayNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    bizTimeDiffMinute,
                    now,
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_DELAY_MONITOR),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_DELAY_MONITOR).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    tradeTransNodeStatus);
            newNodeStatus.add(delayNodeStatus);

            gantryMonitorInfo.getTradeMonitor().setStatus(
                    Math.max(brokenNodeStatus.getStatus(), delayNodeStatus.getStatus())
            );

            remark = String.format("%s|%s",
                    DateFormatUtils.format(dataTransferMonitorInfo.getMonitorTradeTransferTime(), "yyyy-MM-dd HH:mm:ss"),
                    DateFormatUtils.format(dataTransferMonitorInfo.getMonitorTradeBizTime(), "yyyy-MM-dd HH:mm:ss"));

            gantryMonitorInfo.getTradeMonitor().setRemark(remark);
        }

        /* 至部中心交易传输状态 */
        if (dataTransferMonitorInfo.getMinistryTradeTransferTime() != null) {
            long transferTimeDiff = now.getTime() - dataTransferMonitorInfo.getMinistryTradeTransferTime().getTime();
            int transTimeDiffMinute = (int) (transferTimeDiff / 60000.0);
            InfoNodeStatus brokenNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    transTimeDiffMinute,
                    now,
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_BROKEN_MINISTRY),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_BROKEN_MINISTRY).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    tradeTransNodeStatus);
            newNodeStatus.add(brokenNodeStatus);

            long bizTimeDiff = dataTransferMonitorInfo.getMinistryTradeTransferTime().getTime()
                    - dataTransferMonitorInfo.getMinistryTradeBizTime().getTime();
            int bizTimeDiffMinute = (int) (bizTimeDiff / 60000.0);
            InfoNodeStatus delayNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    bizTimeDiffMinute,
                    now,
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_DELAY_MINISTRY),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_DELAY_MINISTRY).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    tradeTransNodeStatus);
            newNodeStatus.add(delayNodeStatus);

            gantryMonitorInfo.getTradeMinistry().setStatus(
                    Math.max(brokenNodeStatus.getStatus(), delayNodeStatus.getStatus())
            );

            remark = String.format("%s|%s",
                    DateFormatUtils.format(dataTransferMonitorInfo.getMinistryTradeTransferTime(), "yyyy-MM-dd HH:mm:ss"),
                    DateFormatUtils.format(dataTransferMonitorInfo.getMinistryTradeBizTime(), "yyyy-MM-dd HH:mm:ss"));

            gantryMonitorInfo.getTradeMinistry().setRemark(remark);
        }

        /* 至省中心交易传输状态 */
        if (dataTransferMonitorInfo.getProvinceTradeTransferTime() != null) {
            long transferTimeDiff = now.getTime() - dataTransferMonitorInfo.getProvinceTradeTransferTime().getTime();
            int transTimeDiffMinute = (int) (transferTimeDiff / 60000.0);
            InfoNodeStatus brokenNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    transTimeDiffMinute,
                    now,
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_BROKEN_PROVINCE),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_BROKEN_PROVINCE).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    tradeTransNodeStatus);
            newNodeStatus.add(brokenNodeStatus);

            long bizTimeDiff = dataTransferMonitorInfo.getProvinceTradeTransferTime().getTime()
                    - dataTransferMonitorInfo.getProvinceTradeBizTime().getTime();
            int bizTimeDiffMinute = (int) (bizTimeDiff / 60000.0);
            InfoNodeStatus delayNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    bizTimeDiffMinute,
                    now,
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_DELAY_PROVINCE),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_TRADE_DELAY_PROVINCE).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    tradeTransNodeStatus);
            newNodeStatus.add(delayNodeStatus);

            gantryMonitorInfo.getTradeProvince().setStatus(
                    Math.max(brokenNodeStatus.getStatus(), delayNodeStatus.getStatus())
            );

            remark = String.format("%s|%s",
                    DateFormatUtils.format(dataTransferMonitorInfo.getProvinceTradeTransferTime(), "yyyy-MM-dd HH:mm:ss"),
                    DateFormatUtils.format(dataTransferMonitorInfo.getProvinceTradeBizTime(), "yyyy-MM-dd HH:mm:ss"));

            gantryMonitorInfo.getTradeProvince().setRemark(remark);
        }

        for (InfoNodeStatus infoNodeStatus : newNodeStatus) {
            nodeStatusMap.put(infoNodeStatus.getKey(), infoNodeStatus);
        }

        nodeStatusMap.put(tradeTransNodeStatus.getKey(), tradeTransNodeStatus);

        gantryMonitorInfo.getTrade().setStatus(tradeTransNodeStatus.getStatus());

        /* 判断父节点的状态 */
        StatusCheckUtils.checkParentNodeStatus(tradeTransNodeStatus.getStatus(),
                tradeTransNodeStatus.getStatusCheckTime(),
                parentNodeStatus);
    }

    /**
     * 检测门架至运行监测系统、门架至省中心、门架至部中心的数据传输状态
     */
    public void vehTransferMonitor(
            OrgInfo orgInfo,
            Map<String, InfoNodeStatus> nodeStatusMap,
            Map<String, DicNodeType> nodeTypeMap,
            InfoNodeStatus parentNodeStatus,
            GantryMonitorInfo gantryMonitorInfo) {

        /* 获取最新检测信息 */
        DataTransferMonitorInfo dataTransferMonitorInfo = getDataTransferMonitorInfoByOrgId(orgInfo.getOrgId());
        /* 无状态，不检测 */
        if (dataTransferMonitorInfo == null) {
            return;
        }

        /* 新状态 */
        List<InfoNodeStatus> newNodeStatus = new ArrayList<>();

        Date now = new Date();

        String orgName = orgInfo.getOrgName();

        String remark = "";

        /* 牌识传输状态 */
        InfoNodeStatus vehTransNodeStatus =
                nodeStatusService.makeNodeStatus(
                        nodeTypeMap.get(BizConstants.NODE_TYPE_VEHDATATRANSFER), orgInfo.getOrgId(), "",
                        orgInfo.getOrgId(),
                        BizConstants.NODE_STATUS_UNKNOWN, orgInfo.getOrgId(), "", new Date(0));

        if (dataTransferMonitorInfo.getMonitorVehTransferTime() != null) {
            /* 至运行监测牌识传输状态 */
            long transferTimeDiff = now.getTime() - dataTransferMonitorInfo.getMonitorVehTransferTime().getTime();
            int transTimeDiffMinute = (int) (transferTimeDiff / 60000.0);
            InfoNodeStatus brokenNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    transTimeDiffMinute,
                    dataTransferMonitorInfo.getMonitorVehCheckTime(),
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_BROKEN_MONITOR),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_BROKEN_MONITOR).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    vehTransNodeStatus);
            newNodeStatus.add(brokenNodeStatus);

            long bizTimeDiff = dataTransferMonitorInfo.getMonitorVehTransferTime().getTime()
                    - dataTransferMonitorInfo.getMonitorVehBizTime().getTime();
            int bizTimeDiffMinute = (int) (bizTimeDiff / 60000.0);
            InfoNodeStatus delayNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    bizTimeDiffMinute,
                    dataTransferMonitorInfo.getMonitorVehCheckTime(),
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_DELAY_MONITOR),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_DELAY_MONITOR).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    vehTransNodeStatus);
            newNodeStatus.add(delayNodeStatus);
            gantryMonitorInfo.getVehMonitor().setStatus(
                    Math.max(brokenNodeStatus.getStatus(), delayNodeStatus.getStatus())
            );

            remark = String.format("%s|%s",
                    DateFormatUtils.format(dataTransferMonitorInfo.getMonitorVehTransferTime(), "yyyy-MM-dd HH:mm:ss"),
                    DateFormatUtils.format(dataTransferMonitorInfo.getMonitorVehBizTime(), "yyyy-MM-dd HH:mm:ss"));

            gantryMonitorInfo.getVehMonitor().setRemark(remark);
        }

        if (dataTransferMonitorInfo.getMinistryVehTransferTime() != null) {
            /* 至部中心牌识传输状态 */
            long transferTimeDiff = now.getTime() - dataTransferMonitorInfo.getMinistryVehTransferTime().getTime();
            int transTimeDiffMinute = (int) (transferTimeDiff / 60000.0);
            InfoNodeStatus brokenNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    transTimeDiffMinute,
                    dataTransferMonitorInfo.getMinistryVehCheckTime(),
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_BROKEN_MINISTRY),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_BROKEN_MINISTRY).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    vehTransNodeStatus);
            newNodeStatus.add(brokenNodeStatus);

            long bizTimeDiff = dataTransferMonitorInfo.getMinistryVehTransferTime().getTime()
                    - dataTransferMonitorInfo.getMinistryVehBizTime().getTime();
            int bizTimeDiffMinute = (int) (bizTimeDiff / 60000.0);
            InfoNodeStatus delayNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    bizTimeDiffMinute,
                    dataTransferMonitorInfo.getMinistryVehCheckTime(),
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_DELAY_MINISTRY),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_DELAY_MINISTRY).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    vehTransNodeStatus);
            newNodeStatus.add(delayNodeStatus);
            gantryMonitorInfo.getVehMinistry().setStatus(
                    Math.max(brokenNodeStatus.getStatus(), delayNodeStatus.getStatus())
            );

            remark = String.format("%s|%s",
                    DateFormatUtils.format(dataTransferMonitorInfo.getMinistryVehTransferTime(), "yyyy-MM-dd HH:mm:ss"),
                    DateFormatUtils.format(dataTransferMonitorInfo.getMinistryVehBizTime(), "yyyy-MM-dd HH:mm:ss"));

            gantryMonitorInfo.getVehMinistry().setRemark(remark);
        }

        if (dataTransferMonitorInfo.getProvinceVehTransferTime() != null) {
            /* 至省中心牌识传输状态 */
            long transferTimeDiff = now.getTime() - dataTransferMonitorInfo.getProvinceVehTransferTime().getTime();
            int transTimeDiffMinute = (int) (transferTimeDiff / 60000.0);
            InfoNodeStatus brokenNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    transTimeDiffMinute,
                    dataTransferMonitorInfo.getProvinceVehCheckTime(),
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_BROKEN_PROVINCE),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_BROKEN_PROVINCE).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    vehTransNodeStatus);
            newNodeStatus.add(brokenNodeStatus);

            long bizTimeDiff = dataTransferMonitorInfo.getProvinceVehTransferTime().getTime()
                    - dataTransferMonitorInfo.getProvinceVehBizTime().getTime();
            int bizTimeDiffMinute = (int) (bizTimeDiff / 60000.0);
            InfoNodeStatus delayNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                    bizTimeDiffMinute,
                    dataTransferMonitorInfo.getProvinceVehCheckTime(),
                    nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_DELAY_PROVINCE),
                    orgInfo.getOrgId(),
                    orgName + split + nodeTypeMap.get(BizConstants.NODE_TYPE_DATATRANSFER_VEH_DELAY_PROVINCE).getNodeTypeName(),
                    orgInfo.getOrgId(),
                    vehTransNodeStatus);
            newNodeStatus.add(delayNodeStatus);
            gantryMonitorInfo.getVehProvince().setStatus(
                    Math.max(brokenNodeStatus.getStatus(), delayNodeStatus.getStatus())
            );

            remark = String.format("%s|%s",
                    DateFormatUtils.format(dataTransferMonitorInfo.getProvinceVehTransferTime(), "yyyy-MM-dd HH:mm:ss"),
                    DateFormatUtils.format(dataTransferMonitorInfo.getProvinceVehBizTime(), "yyyy-MM-dd HH:mm:ss"));

            gantryMonitorInfo.getVehProvince().setRemark(remark);
        }

        for (InfoNodeStatus infoNodeStatus : newNodeStatus) {
            nodeStatusMap.put(infoNodeStatus.getKey(), infoNodeStatus);
        }

        nodeStatusMap.put(vehTransNodeStatus.getKey(), vehTransNodeStatus);

        gantryMonitorInfo.getVeh().setStatus(vehTransNodeStatus.getStatus());

        /* 判断父节点的状态 */
        StatusCheckUtils.checkParentNodeStatus(vehTransNodeStatus.getStatus(),
                vehTransNodeStatus.getStatusCheckTime(),
                parentNodeStatus);
    }

    /**
     * 查询数据传输状态
     *
     * @param orgId
     * @return
     */
    private DataTransferMonitorInfo getDataTransferMonitorInfoByOrgId(String orgId) {

        Date now = new Date();
        DataTransferMonitorInfo dataTransferMonitorInfo = new DataTransferMonitorInfo();
        /* 获取到运行监测的交易数据传输情况 */
        String dataTransInfoRsuKey = BizConstants.REDIS_KEY_PRE_GANTRY_DATA_TRANS_INFO_RSU + orgId;
        String jsonString = redisUtil.get(dataTransInfoRsuKey);
        DataTransInfo dataTransInfo = null;
        if (jsonString == null) {
            dataTransInfo = new DataTransInfo(orgId, BizConstants.ORG_TYPE_GANTRY_FRONT);
        } else {
            dataTransInfo = JSON.parseObject(jsonString, DataTransInfo.class);
        }
        dataTransferMonitorInfo.setMonitorTradeBizTime(dataTransInfo.getLastTime());
        dataTransferMonitorInfo.setMonitorTradeTransferTime(dataTransInfo.getLastChangeTime());
        dataTransferMonitorInfo.setMonitorTradeCheckTime(now);
        /* 获取到运行监测的牌识数据传输情况 */
        String dataTransInfoCameraKey = BizConstants.REDIS_KEY_PRE_GANTRY_DATA_TRANS_INFO_CAMERA + orgId;
        jsonString = redisUtil.get(dataTransInfoCameraKey);
        if (jsonString == null) {
            dataTransInfo = new DataTransInfo(orgId, BizConstants.ORG_TYPE_GANTRY_FRONT);
        } else {
            dataTransInfo = JSON.parseObject(jsonString, DataTransInfo.class);
        }
        dataTransferMonitorInfo.setMonitorVehBizTime(dataTransInfo.getLastTime());
        dataTransferMonitorInfo.setMonitorVehTransferTime(dataTransInfo.getLastChangeTime());
        dataTransferMonitorInfo.setMonitorVehCheckTime(now);
        /* 获取到部中心和省中心的交易数据传输情况 */
        InfoGantryUploadStatus infoGantryUploadStatus = dataTransferMapper.getGantryUploadInfoByOrgId(orgId);
        if (infoGantryUploadStatus != null) {
            dataTransferMonitorInfo.setProvinceTradeBizTime(DateUtils.parseDate(infoGantryUploadStatus.getTradeTransTime()));
            dataTransferMonitorInfo.setProvinceTradeTransferTime(DateUtils.parseDate(infoGantryUploadStatus.getTradeUploadTime()));
            dataTransferMonitorInfo.setProvinceTradeCheckTime(infoGantryUploadStatus.getCheckTime());
            dataTransferMonitorInfo.setMinistryTradeBizTime(DateUtils.parseDate(infoGantryUploadStatus.getMtradeTransTime()));
            dataTransferMonitorInfo.setMinistryTradeTransferTime(DateUtils.parseDate(infoGantryUploadStatus.getMtradeUploadTime()));
            dataTransferMonitorInfo.setMinistryTradeCheckTime(infoGantryUploadStatus.getCheckTime());
            dataTransferMonitorInfo.setProvinceVehBizTime(DateUtils.parseDate(infoGantryUploadStatus.getVehPicTime()));
            dataTransferMonitorInfo.setProvinceVehTransferTime(DateUtils.parseDate(infoGantryUploadStatus.getVehUploadTime()));
            dataTransferMonitorInfo.setProvinceVehCheckTime(infoGantryUploadStatus.getCheckTime());
            dataTransferMonitorInfo.setMinistryVehBizTime(DateUtils.parseDate(infoGantryUploadStatus.getMvehPicTime()));
            dataTransferMonitorInfo.setMinistryVehTransferTime(DateUtils.parseDate(infoGantryUploadStatus.getMvehUploadTime()));
            dataTransferMonitorInfo.setMinistryVehCheckTime(infoGantryUploadStatus.getCheckTime());
        } else {
            Date date0 = new Date(0);
            dataTransferMonitorInfo.setProvinceTradeBizTime(date0);
            dataTransferMonitorInfo.setProvinceTradeTransferTime(date0);
            dataTransferMonitorInfo.setProvinceTradeCheckTime(now);
            dataTransferMonitorInfo.setMinistryTradeBizTime(date0);
            dataTransferMonitorInfo.setMinistryTradeTransferTime(date0);
            dataTransferMonitorInfo.setMinistryTradeCheckTime(now);
            dataTransferMonitorInfo.setProvinceVehBizTime(date0);
            dataTransferMonitorInfo.setProvinceVehTransferTime(date0);
            dataTransferMonitorInfo.setProvinceVehCheckTime(now);
            dataTransferMonitorInfo.setMinistryVehBizTime(date0);
            dataTransferMonitorInfo.setMinistryVehTransferTime(date0);
            dataTransferMonitorInfo.setMinistryVehCheckTime(now);
        }
        return dataTransferMonitorInfo;
    }
}
